/*
--------------------------------------------------------------------------------
				Ak-Lib. 
			 Project       	: Ak-Lib
			 Group         	: Ak-Lib R&D Team
			 Author        	: Ocean.Wang
			 Create Date 	: 05-01-2010
--------------------------------------------------------------------------------
Code Name 	:  A.K 	~v~
Description	:  Yet Another Cross-Platform Lib.
Cautions    	:
--------------------------------------------------------------------------------
Change History:
Version		: 0.1
Building 		: 05/01/10
10-05.01 first draft, build, debug and test.
--------------------------------------------------------------------------------
*/

#include "ak_htbl.h"
#include "ak_gears.h"

/* HTbl Lru */

/* HTbl Sis */
static 	_t_sysKLFunc 	_gTest_KLFuncSis;
static 	_t_hTblSiS 		_gTest_hTblSis;

#define _TEST_HTBL_CNT 	0X1000
static 	int 			_gTest_hTblKey[_TEST_HTBL_CNT];
static 	_t_sysLruCi 	_gTest_hTblCi_Up[_TEST_HTBL_CNT];
static 	_t_sysLruCi 	_gTest_hTblCi_Dn[_TEST_HTBL_CNT];

static 	int 	_HTblTest_KeyComp(_t_rbnode * node1, _t_rbnode * node2)
{
	unsigned long long   key1;
	unsigned long long   key2;

	key1 = *((unsigned int *)((_O_PARENT(_t_sysLruCi, mi.kNode, node1))->pKey));
	key2 = *((unsigned int *)((_O_PARENT(_t_sysLruCi, mi.kNode, node2))->pKey));

	if(key1 > key2){
		return _TREE_GREAT;
	}else if(key1 < key2){
		return _TREE_LESS;
	}

	return _TREE_EQUAL;
}

static 	int 	_HTblTest_SisInit(void)
{
	int 			i;
	_t_sysLruCi  * 	pCi;
	_t_sysKLFunc * 	pKLFunc;
	_t_hTblSiS 	 * 	pHTblSis;

	pKLFunc = &(_gTest_KLFuncSis);
	pHTblSis= &(_gTest_hTblSis);
	
	_KLFUNC_INIT(pKLFunc, 
		_HTblTest_KeyComp,  
		NULL, NULL, 
		NULL, NULL);
	SHTblSis_Init(pHTblSis, pKLFunc);

	for(i=0; i<_TEST_HTBL_CNT; i++){
		_gTest_hTblKey[i] = i;
		pCi = &(_gTest_hTblCi_Up[i]);
		pCi->pKey = &(_gTest_hTblKey[i]);
		pCi->lKey = sizeof(int);
	}
	return 0;
}


static 	int 	_HTblTest_SisAdd(void)
{
	int i;
	unsigned int iBucket;
	_t_hTblSiS 	 * 	pHTblSis;
	_t_sysLruCi  * 	pCi;

	pHTblSis= &(_gTest_hTblSis);
	/* Add */
	for(i=0; i<_TEST_HTBL_CNT; i++){
		pCi = &(_gTest_hTblCi_Up[i]);
		iBucket = (_gTest_hTblKey[i] % 256);
		SHTblSis_Add(pHTblSis, &(pCi->mi.kNode), iBucket);
	}
	return 0;
}

static 	int 	_HTblTest_SisFind(void)
{
	int i;
	unsigned int iBucket;
	_t_hTblSiS 	 * 	pHTblSis;
	_t_sysLruCi  * 	pCi;
	_t_rbnode 	 * 	pNode;
	_t_sysLruCi 	tCi;

	pHTblSis= &(_gTest_hTblSis);
	/* Find */
	for(i=0; i<_TEST_HTBL_CNT; i++){
		tCi.pKey = &(_gTest_hTblKey[i]);
		tCi.lKey = sizeof(int);
		iBucket = (_gTest_hTblKey[i] % 256);
		pNode = SHTblSis_Find(pHTblSis, &(tCi.mi.kNode), iBucket);
		if(pNode){
			pCi = _O_PARENT(_t_sysLruCi, mi.kNode, pNode);
			if((pCi - _gTest_hTblCi_Up) != i){
				printf("%d Key %d (%p - %p)!\n", i, _gTest_hTblKey[i], pCi, (_gTest_hTblCi_Up + i));
			}
		}else{
			printf("%d Key %d Not Found!\n", i, _gTest_hTblKey[i]);
		}
	}
	return 0;
}


static 	int 	_HTblTest_SisDel(void)
{
	int i;
	unsigned int iBucket;
	_t_hTblSiS 	 * 	pHTblSis;
	_t_sysLruCi  * 	pCi;
	_t_rbnode 	 * 	pNode;
	_t_sysLruCi 	tCi;

	pHTblSis= &(_gTest_hTblSis);
	/* Del */
	for(i=0; i<_TEST_HTBL_CNT; i++){
		tCi.pKey = &(_gTest_hTblKey[i]);
		tCi.lKey = sizeof(int);
		iBucket = (_gTest_hTblKey[i] % 256);
		pNode = SHTblSis_Del(pHTblSis, &(tCi.mi.kNode), iBucket);
		if(pNode){
			pCi = _O_PARENT(_t_sysLruCi, mi.kNode, pNode);
			if((pCi - _gTest_hTblCi_Up) != i){
				printf("%d Key %d (%p - %p)!\n", i, _gTest_hTblKey[i], pCi, (_gTest_hTblCi_Up + i));
			}
		}else{
			printf("%d Key %d Not Found!\n", i, _gTest_hTblKey[i]);
		}
	}
	return 0;
}


static 	int 	_HTblTest_SisDelEx(void)
{
	int i;
	unsigned int iBucket;
	_t_hTblSiS 	 * 	pHTblSis;
	_t_sysLruCi  * 	pCi;
	_t_rbnode 	 * 	pNode;

	pHTblSis= &(_gTest_hTblSis);
	/* DelEx */
	for(i=0; i<_TEST_HTBL_CNT; i++){
		pCi 	= &(_gTest_hTblCi_Up[i]);
		iBucket = (_gTest_hTblKey[i] % 256);
		pNode = SHTblSis_DelEx(pHTblSis, &(pCi->mi.kNode), iBucket);
		if(pNode){
			pCi = _O_PARENT(_t_sysLruCi, mi.kNode, pNode);
			if((pCi - _gTest_hTblCi_Up) != i){
				printf("%d Key %d (%p - %p)!\n", i, _gTest_hTblKey[i], pCi, (_gTest_hTblCi_Up + i));
			}
		}else{
			printf("%d Key %d Not Found!\n", i, _gTest_hTblKey[i]);
		}
	}
	return 0;
}

static 	int 	_HTblTest_SisTest(void)
{
	_HTblTest_SisAdd();
	_HTblTest_SisFind();
	_HTblTest_SisDel();

	_HTblTest_SisAdd();
	_HTblTest_SisFind();
	_HTblTest_SisDelEx();

	return 0;
}

/* HTbl Bis */
static 	_t_hTblBiS 		_gTest_hTblBis;
static 	_t_sysKLFunc 	_gTest_KLFuncBis_Up;
static 	_t_sysKLFunc 	_gTest_KLFuncBis_Dn;

static 	int 	_HTblTest_BisInit(void)
{
	int 			i;
	_t_sysLruCi  * 	pCi;
	_t_sysKLFunc * 	pKLFuncUp;
	_t_sysKLFunc * 	pKLFuncDn;
	_t_hTblBiS 	 * 	pHTblBis;

	pKLFuncUp 	= &(_gTest_KLFuncBis_Up);
	pKLFuncDn 	= &(_gTest_KLFuncBis_Dn);
	pHTblBis	= &(_gTest_hTblBis);
	
	_KLFUNC_INIT(pKLFuncUp, 
		_HTblTest_KeyComp,  
		NULL, NULL, 
		NULL, NULL);
	_KLFUNC_INIT(pKLFuncDn, 
		_HTblTest_KeyComp,  
		NULL, NULL, 
		NULL, NULL);
	SHTblBis_Init(pHTblBis, pKLFuncUp, pKLFuncDn);

	for(i=0; i<_TEST_HTBL_CNT; i++){
		_gTest_hTblKey[i] = i;
		pCi = &(_gTest_hTblCi_Up[i]);
		pCi->pKey = &(_gTest_hTblKey[i]);
		pCi->lKey = sizeof(int);
		
		pCi = &(_gTest_hTblCi_Dn[i]);
		pCi->pKey = &(_gTest_hTblKey[i]);
		pCi->lKey = sizeof(int);
	}
	return 0;
}


static 	int 	_HTblTest_BisAdd(void)
{
	int i;
	unsigned int iBucket;
	_t_hTblBiS 	 * 	pHTblBis;
	_t_sysLruCi  * 	pCi;

	pHTblBis= &(_gTest_hTblBis);
	/* Add */
	for(i=0; i<_TEST_HTBL_CNT; i++){
		pCi = &(_gTest_hTblCi_Up[i]);
		iBucket = (_gTest_hTblKey[i] % 256);
		SHTblBis_Add(pHTblBis, _bHTBL_UP, &(pCi->mi.kNode), iBucket);

		pCi = &(_gTest_hTblCi_Dn[i]);
		iBucket = (_gTest_hTblKey[i] % 256);
		SHTblBis_Add(pHTblBis, _bHTBL_DN, &(pCi->mi.kNode), iBucket);
	}
	return 0;
}


static 	int 	_HTblTest_BisFind(void)
{
	int i;
	unsigned int iBucket;
	_t_hTblBiS 	 * 	pHTblBis;
	_t_sysLruCi  * 	pCi;
	_t_rbnode 	 * 	pNode;
	_t_sysLruCi 	tCi;

	pHTblBis= &(_gTest_hTblBis);
	/* Find */
	for(i=0; i<_TEST_HTBL_CNT; i++){
		tCi.pKey = &(_gTest_hTblKey[i]);
		tCi.lKey = sizeof(int);
		iBucket = (_gTest_hTblKey[i] % 256);
		
		pNode = SHTblBis_Find(pHTblBis, _bHTBL_UP, &(tCi.mi.kNode), iBucket);
		if(pNode){
			pCi = _O_PARENT(_t_sysLruCi, mi.kNode, pNode);
			if((pCi - _gTest_hTblCi_Up) != i){
				printf("%d Key %d (%p - %p)!\n", i, _gTest_hTblKey[i], pCi, (_gTest_hTblCi_Up + i));
			}
		}else{
			printf("%d Key %d Not Found!\n", i, _gTest_hTblKey[i]);
		}

		pNode = SHTblBis_Find(pHTblBis, _bHTBL_DN, &(tCi.mi.kNode), iBucket);
		if(pNode){
			pCi = _O_PARENT(_t_sysLruCi, mi.kNode, pNode);
			if((pCi - _gTest_hTblCi_Dn) != i){
				printf("%d Key %d (%p - %p)!\n", i, _gTest_hTblKey[i], pCi, (_gTest_hTblCi_Dn + i));
			}
		}else{
			printf("%d Key %d Not Found!\n", i, _gTest_hTblKey[i]);
		}

	}
	return 0;
}


static 	int 	_HTblTest_BisDel(void)
{
	int i;
	unsigned int iBucket;
	_t_hTblBiS 	 * 	pHTblBis;
	_t_sysLruCi  * 	pCi;
	_t_rbnode 	 * 	pNode;
	_t_sysLruCi 	tCi;

	pHTblBis= &(_gTest_hTblBis);
	/* Del */
	for(i=0; i<_TEST_HTBL_CNT; i++){
		tCi.pKey = &(_gTest_hTblKey[i]);
		tCi.lKey = sizeof(int);
		iBucket = (_gTest_hTblKey[i] % 256);
		
		pNode = SHTblBis_Del(pHTblBis, _bHTBL_UP, &(tCi.mi.kNode), iBucket);
		if(pNode){
			pCi = _O_PARENT(_t_sysLruCi, mi.kNode, pNode);
			if((pCi - _gTest_hTblCi_Up) != i){
				printf("%d Key %d (%p - %p)!\n", i, _gTest_hTblKey[i], pCi, (_gTest_hTblCi_Up + i));
			}
		}else{
			printf("%d Key %d Not Found!\n", i, _gTest_hTblKey[i]);
		}

		pNode = SHTblBis_Del(pHTblBis, _bHTBL_DN, &(tCi.mi.kNode), iBucket);
		if(pNode){
			pCi = _O_PARENT(_t_sysLruCi, mi.kNode, pNode);
			if((pCi - _gTest_hTblCi_Dn) != i){
				printf("%d Key %d (%p - %p)!\n", i, _gTest_hTblKey[i], pCi, (_gTest_hTblCi_Dn + i));
			}
		}else{
			printf("%d Key %d Not Found!\n", i, _gTest_hTblKey[i]);
		}
	}
	return 0;
}


static 	int 	_HTblTest_BisDelEx(void)
{
	int i;
	unsigned int iBucket;
	_t_hTblBiS 	 * 	pHTblBis;
	_t_sysLruCi  * 	pCi;
	_t_rbnode 	 * 	pNode;

	pHTblBis= &(_gTest_hTblBis);
	/* Del */
	for(i=0; i<_TEST_HTBL_CNT; i++){
		iBucket = (_gTest_hTblKey[i] % 256);
		
		pCi = &_gTest_hTblCi_Up[i];
		pNode = SHTblBis_DelEx(pHTblBis, _bHTBL_UP, &(pCi->mi.kNode), iBucket);
		if(pNode){
			pCi = _O_PARENT(_t_sysLruCi, mi.kNode, pNode);
			if((pCi - _gTest_hTblCi_Up) != i){
				printf("%d Key %d (%p - %p)!\n", i, _gTest_hTblKey[i], pCi, (_gTest_hTblCi_Up + i));
			}
		}else{
			printf("%d Key %d Not Found!\n", i, _gTest_hTblKey[i]);
		}

		pCi = &_gTest_hTblCi_Dn[i];
		pNode = SHTblBis_DelEx(pHTblBis, _bHTBL_DN, &(pCi->mi.kNode), iBucket);
		if(pNode){
			pCi = _O_PARENT(_t_sysLruCi, mi.kNode, pNode);
			if((pCi - _gTest_hTblCi_Dn) != i){
				printf("%d Key %d (%p - %p)!\n", i, _gTest_hTblKey[i], pCi, (_gTest_hTblCi_Dn + i));
			}
		}else{
			printf("%d Key %d Not Found!\n", i, _gTest_hTblKey[i]);
		}
	}
	return 0;
}

static 	int 	_HTblTest_BisTest(void)
{
	_HTblTest_BisAdd();
	_HTblTest_BisFind();
	_HTblTest_BisDel();

	_HTblTest_BisAdd();
	_HTblTest_BisFind();
	_HTblTest_BisDelEx();

	return 0;
}

/* HTbl Lv */
static 	_t_hTblLvS 	_gTest_hTblLvs;
/* 
0: Plmn  
1: Lac 
2: Rac 
*/
static 	int 		_gTest_LvsKey[3];
static 	int 	_HTblTest_LvsInit(void)
{
	int 			i;
	_t_hTblLvS 	 * 	pHTblLvs;
	_t_sysLruCi  * 	pCi;

	pHTblLvs= &(_gTest_hTblLvs);
	
	SHTblLv_Init(pHTblLvs, 8);
	for(i=0; i<_TEST_HTBL_CNT; i++){
		pCi = &(_gTest_hTblCi_Up[i]);
		pCi->pKey = &(_gTest_hTblKey[i]);
		pCi->lKey = sizeof(int);
	}

	return 0;
}

static 	int 	_HTblTest_LvsAdd(void)
{
	int 			i, key;
	_t_hTblLvS 	 * 	pHTblLvs;
	_t_sysLruCi  * 	pCi;

	pHTblLvs= &(_gTest_hTblLvs);
	/* Add */
	for(i=0; i<_TEST_HTBL_CNT; i++){
		pCi = &(_gTest_hTblCi_Up[i]);
		key = *((int *)pCi->pKey);
		_gTest_LvsKey[0] = key & 0X01;
		_gTest_LvsKey[1] = key >> 8;
		_gTest_LvsKey[2] = key & 0X0000000F;
		SHTblLv_TblAdd(pHTblLvs, _gTest_LvsKey, 3, &(pCi->mi.aNode));
	}
	return 0;
	
}

static 	int 	_HTblTest_LvsFind(void)
{
	int 			i, key;
	_t_hTblLvS 	 * 	pHTblLvs;
	_t_hTblLv_Hdl* 	pHdl;
	_t_sysLruCi  * 	pCi;

	pHTblLvs= &(_gTest_hTblLvs);
	/* Add */
	for(i=0; i<_TEST_HTBL_CNT; i++){
		pCi = &(_gTest_hTblCi_Up[i]);
		key = *((int *)pCi->pKey);
		_gTest_LvsKey[0] = key & 0X01;
		_gTest_LvsKey[1] = key >> 8;
		_gTest_LvsKey[2] = key & 0X0000000F;
		pHdl = SHTblLv_TblFind(pHTblLvs, _gTest_LvsKey, 3);
		if(pHdl){
			printf("[%08x] %d - %d - %d : (%p) Cnt:(%ld)\n", 
					key,
					_gTest_LvsKey[0],
					_gTest_LvsKey[1],
					_gTest_LvsKey[2],
					pHdl, pHdl->sQue.count);
		}else{
			printf("[%08x] %d - %d - %d : (%p) \n", 
					key,
					_gTest_LvsKey[0],
					_gTest_LvsKey[1],
					_gTest_LvsKey[2],
					pHdl);
		}
	}
	return 0;
	
}

static 	int 	_HTblTest_LvsDel(void)
{
	int 			i, key;
	_t_hTblLvS 	 * 	pHTblLvs;
	_t_sysLruCi  * 	pCi;

	pHTblLvs= &(_gTest_hTblLvs);
	/* Add */
	for(i=0; i<_TEST_HTBL_CNT; i++){
		pCi = &(_gTest_hTblCi_Up[i]);
		key = *((int *)pCi->pKey);
		_gTest_LvsKey[0] = key & 0X01;
		_gTest_LvsKey[1] = key >> 8;
		_gTest_LvsKey[2] = key & 0X0000000F;
		SHTblLv_TblDel(pHTblLvs, _gTest_LvsKey, 3, &(pCi->mi.aNode));
	}
	return 0;
	
}


static 	int 	_HTblTest_LvsTest(void)
{
	_HTblTest_LvsAdd();
	_HTblTest_LvsFind();
	_HTblTest_LvsDel();

	return 0;
}

int 	main(void)
{
	_HTblTest_SisInit();
	_HTblTest_SisTest();

	
	_HTblTest_BisInit();
	_HTblTest_BisTest();

	_HTblTest_LvsInit();
	_HTblTest_LvsTest();
	return 0;
}
